home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "dnsconf.h"
- #include "internal.h"
-
- /*
- fgets with support for continuation line
- */
- static char *record_fgets(
- char *buf,
- int size,
- FILE *fin)
- {
- char *ret = NULL;
- bool cont = false;
- while (fgets(buf,size,fin)!=NULL){
- if (ret == NULL) ret = buf;
- char *ptp = strchr (buf,';');
- if (ptp != NULL) *ptp = '\0';
- char *ptc = strchr (buf,'(');
- char *pte = strchr (buf,')');
- if (ptc != NULL){
- // Openning parenthese
- *ptc = ' ';
- cont = true;
- }else if (pte != NULL){
- // Closing parenthese
- *pte = ' ';
- cont = false;
- }
- if (!cont) break;
- int len = strlen(buf);
- buf += len;
- size -= len;
- }
- return ret;
- }
-
-
- PUBLIC ORIGIN::ORIGIN (const char *_origin)
- {
- origin.setfrom (_origin);
- }
-
- PUBLIC void ORIGIN::print(bool save_ori, TBFILE &tbf) const
- {
- // We don't put $ORIGIN at the beginning of the file
- // because it is implied
- if (save_ori) fprintf (tbf.cur,"$ORIGIN %s\n",origin.get());
- tbrec.save(tbf);
- }
-
- PUBLIC void ORIGIN::edit()
- {
- }
-
- /*
- Locate all IP number in use in that area (sub origin) of a domain.
- Return the number added to adrs
- */
- PUBLIC int ORIGIN::getalladr(IP_ADDRS &adrs)
- {
- int ret = 0;
- int n = tbrec.getnb();
- for (int i=0; i<n; i++){
- RECORD *rec = tbrec.getitem(i);
- if (rec->is(RTYPE_A)){
- RECORD_IN_A *in = (RECORD_IN_A*)rec;
- adrs.add (new IP_ADDR(in->addr));
- ret++;
- }
- }
- return ret;
- }
-
-
- /*
- Return != if any component of the ORIGIN was modified
- */
- PUBLIC int ORIGIN::was_modified()
- {
- int ret = ARRAY_OBJ::was_modified();
- if (!ret){
- ret = tbrec.was_modified();
- }
- return ret;
- }
-
-
- PRIVATE int ORIGINS::parsespecial(
- const char *key,
- const char *pt,
- TBFILE &tbf,
- ORIGIN *&ori)
- {
- int ret = 0;
- pt = str_skip(pt);
- char arg[200];
- pt = str_copyword (arg,pt);
- if (stricmp(key,"$ORIGIN")==0){
- ori = new ORIGIN(arg);
- add (ori);
- }else if (stricmp(key,"$INCLUDE")==0){
- ori->tbrec.add (new RECORD_INCLUDE(arg));
- ret = tbf.fopen (arg,"r") != NULL ? 0 : -1;
- }else{
- ret = -1;
- }
- return ret;
- }
- /*
- Complete the parsing of the line, pt point to the TTL maybe
- Return NULL if any error or a new RECORD.
- */
- PRIVATE int ORIGINS::parseend (
- char *pt,
- RECORD_PARSE &p,
- ORIGIN *ori)
- {
- int ret = -1;
- pt = str_skip(pt);
- if (isdigit(*pt)){
- p.ttl = atoi(pt);
- p.nottl = false;
- while (isdigit(*pt)) pt++;
- pt = str_skip(pt);
- }
- char keyword[200];
- pt = str_copyword (keyword,pt);
- if (stricmp(keyword,"IN")==0){
- pt = str_skip(pt);
- pt = str_copyword (keyword,pt);
- pt = str_skip(pt);
- pt = str_copyword (p.f2,pt);
- pt = str_skip(pt);
- pt = str_copyword (p.f3,pt);
- pt = str_skip(pt);
- pt = str_copyword (p.f4,pt);
- pt = str_skip(pt);
- pt = str_copyword (p.f5,pt);
- pt = str_skip(pt);
- pt = str_copyword (p.f6,pt);
- pt = str_skip(pt);
- pt = str_copyword (p.f7,pt);
- pt = str_skip(pt);
- pt = str_copyword (p.f8,pt);
- RECORD *o = NULL;
- if (stricmp(keyword,"A")==0){
- o = new RECORD_IN_A(p);
- }else if (stricmp(keyword,"MX")==0){
- o = new RECORD_IN_MX(p);
- }else if (stricmp(keyword,"NS")==0){
- o = new RECORD_IN_NS(p);
- }else if (stricmp(keyword,"PTR")==0){
- o = new RECORD_IN_PTR(p);
- }else if (stricmp(keyword,"CNAME")==0){
- o = new RECORD_IN_CNAME(p);
- }else if (stricmp(keyword,"SOA")==0){
- o = new RECORD_IN_SOA(p);
- }
- if (o != NULL){
- ori->tbrec.add(o);
- ret = 0;
- }else{
- ret = -1;
- }
- }
- return ret;
- }
-
-
- PUBLIC ORIGIN *ORIGINS::getitem(int no) const
- {
- return (ORIGIN*)ARRAY::getitem(no);
- }
-
- /*
- Read a file with a bunch of IN records and manage those.
- */
- PUBLIC int ORIGINS::read (
- const char *named_dir,
- const char *fname,
- const char *first_origin)
- {
- /*
- Reading a record file is complicate. It may contain
- several $origin statement and several $include statement.
-
- We maintain the records as a set of several origin related
- list. In those list, we maintain special record indicating
- the beginning and end of an include file scope.
- */
- ORIGIN *ori = new ORIGIN(first_origin);
- add (ori);
- int ret = -1;
- TBFILE tbf(named_dir);
- tbf.fopen(fname,"r");
- while (tbf.cur != NULL){
- char buf[10000];
- ret = 0;
- while (record_fgets(buf,sizeof(buf)-1,tbf.cur)!=NULL){
- strip_end (buf);
- RECORD_PARSE parse;
- if (buf[0] > ' ' && buf[0] != ';'){
- char *pt = str_copyword (parse.f1,buf);
- if (parse.f1[0] == '$'){
- ret = parsespecial (parse.f1,pt
- ,tbf,ori);
- }else{
- ret = parseend (pt,parse,ori);
- }
- }else if (buf[0] != '\0'){
- char *pt = str_skip (buf);
- if (*pt == ';'){
- ori->tbrec.add (new RECORD_COMMENT(buf));
- }else{
- ret = parseend (pt,parse,ori);
- }
- }
- }
- tbf.fclose ();
- if (tbf.cur != NULL) ori->tbrec.add (new RECORD_END_INCLUDE);
- }
- return ret;
- }
-
- /*
- Save in a file a bunch of IN records.
- */
- PUBLIC int ORIGINS::save (
- const char *named_dir,
- const char *fname) const
- {
- int ret = -1;
- TBFILE tbf(named_dir);
- if (tbf.fopen(fname,"w") != NULL){
- ret = 0;
- for (int i=0; i<getnb(); i++){
- getitem(i)->print (i != 0 ,tbf);
- }
- }
- return ret;
- }
-
-